﻿// Original author contact info: Owen Emlen (owene_1998@yahoo.com)
// Note: other individuals may also have contributed to this code
// Project hosted on CodePlex.com as of 1/10/2009 at http://www.codeplex.com/EmlenMud
using System.Runtime.Serialization;
using System;
using System.Xml.Serialization;
using System.Threading;
using System.ComponentModel;
#if USE_HYPER
using Hyper.ComponentModel;
#endif

namespace BrainTechLLC.ThreadSafeObjects
{
#if NO_SILVERLIGHT
    [TypeDescriptionProvider(typeof(HyperTypeDescriptionProvider))]
#endif
    [Serializable]
    [DataContract]
    public abstract class GenericCacheAbstractBase<T> : CacheBase, ICacheBase<T>
    {
        [NonSerialized, XmlIgnore]
        public TPopulateCacheDelegate<T> _populateCacheDelegate;

        [NonSerialized, XmlIgnore]
        public TPopulateCacheDelegateDirect<T> _populateCacheDelegateDirect;

        public GenericCacheAbstractBase(TPopulateCacheDelegate<T> populateCacheDelegate) { SetPopulateCacheDelegate(populateCacheDelegate); }
        public GenericCacheAbstractBase(TPopulateCacheDelegateDirect<T> populateCacheDelegate) { SetPopulateCacheDelegate(populateCacheDelegate); }
        public GenericCacheAbstractBase() { }

        public abstract bool IsCacheValid(object populateCacheParameter);
        public abstract bool IsCacheValid();

        /// <summary>
        /// Sets the delegate used to populate the cache
        /// </summary>
        /// <param name="populateCacheDelegate"></param>
        public virtual void SetPopulateCacheDelegate(TPopulateCacheDelegate<T> populateCacheDelegate)
        {
            if (_populateCacheDelegate == null)
                Interlocked.CompareExchange<TPopulateCacheDelegate<T>>(ref _populateCacheDelegate, populateCacheDelegate, null);
        }

        public virtual void SetPopulateCacheDelegate(TPopulateCacheDelegateDirect<T> populateCacheDelegate)
        {
            if (_populateCacheDelegateDirect == null)
                Interlocked.CompareExchange<TPopulateCacheDelegateDirect<T>>(ref _populateCacheDelegateDirect, populateCacheDelegate, null);
        }

        /// <summary>
        /// Retrieves the cached item, given a populateCache parameter and other arguments
        /// </summary>
        public abstract T GetItem(object populateCacheParameter, params object[] args);

        /// <summary>
        /// Retrieves the cached object
        /// </summary>
        public virtual T GetItem()
        {
            return GetItem(_defaultPopulateParam, _storedArgs);
        }
    }
}
